package ks.server.ipc;


import ks.framework.common.Message;
import ks.framework.communicator.Communicator;
import ks.framework.interfaces.IAuthorization;
import ks.framework.interfaces.ICommunicator;
import ks.framework.interfaces.IServerConnection;
import ks.server.processor.Processor;

/**
 * Server processes requests received from client.
 */
public class Server implements IServerConnection {
	
	/** Server Version. */
	public static final String version = "2.1";

	/** Server Version Date. */
	public static final String versionDate = "2009-Oct-29-23-08-11";

	/** Listener for client requests. */
	Listener listener = null;

	/** Authentication. */
	IAuthorization auth;
	
	/** Communicator for responses to the client(s). */
	Communicator com = null;
	
	/** Default port to be listened for. */
	public static final int defaultPort = 7878;
	
	/** Port to listen for. */
	int port;
	
	/** 
	 * Construct a server with no authentication.
	 */
	public Server () {
		this(null, defaultPort);
	}
	
	/** 
	 * Construct a server with given entity to manage authorization requests.
	 *  
	 * @param auth   Authentication agent to use (or null if none).
	 */
	public Server (IAuthorization auth) {
		this(auth, defaultPort);
	}
	
	/** 
	 * Construct a server with authorization manager and different port.
	 * <p>
	 * @param auth   Authentication agent to use (or null if none).
	 * @param port   Port on which server will be listening for connections.
	 */
	public Server(IAuthorization auth, int port) { 
		this.auth = auth;
		this.port = port;
	}
	
	/** 
	 * Construct a server with no authentication on given port.
	 */
	public Server(int port) {
		this(null, port);
	}

	/**
	 * Activate server. Prevent multiple access here
	 */
	public synchronized boolean activate() {

		listener = new Listener(this, port);
		boolean response = listener.start();
			
		com = new Communicator();
		return response;
	}


	/**
	 * Close listener.
	 */
	public void deactivate() {
		if (listener != null) {
			System.err.println ("Shutting down server.");
			listener.killServer();
			listener = null;
			com = null;
		}
	}

	/**
	 * Receive message from client and hand off to our controller.
	 * <p>
	 * Make sure Message can't be spoofed since we set the incoming originator
	 * here.
	 * 
	 * @param who       user making the request
	 * @param incoming  message coming from client
	 */
	public void process(String who, Message incoming) {
		incoming.setOriginator(who);
		
		// pass off to processor
		new Processor(com).process(incoming);
	}


	/**
	 * Determine whether user can self-register according to the declared 
	 * authorization entity. 
	 * 
	 * Should no authorization entity exist, then return true
	 *  
	 * @param who
	 * @param pwd
	 * @return
	 */
	public boolean selfRegister(String who, String pwd) {
		if (auth == null ) { 
			return true; 
		}
		
		return auth.selfRegister(who, pwd);
	}
	
	/**
	 * Determine whether user is authorized, according to the declared
	 * authorization entity.
	 * <p>
	 * If there is no authenticating agent, then returns true always
	 * 
	 * @param user   user to be authorized
	 * @param pass   associated pass pharse with user
	 * @return
	 */
	public boolean authorize(String user, String pass) {
		if (auth == null) {
			return true;
		}
		
		return auth.authorize(user, pass);
	}

	@Override
	public boolean connectUser(String userName, ICommunicator agent) {
		return com.connectUser(userName, agent);
	}

	@Override
	public boolean disconnectUser(String userName) {
		return com.disconnectUser(userName);
	}

	/** Enable externals to access communicator to talk to client. */
	public Communicator getCommunicator() {
		return com;
	}

}